/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#include "StdAfx.h"
#include "MWinSecurity.h"

MWinSecurity::MWinSecurity(void)
{
}

MWinSecurity::~MWinSecurity(void)
{
}

LPTSTR MWinSecurity::RetrieveFormatedUserName(EXTENDED_NAME_FORMAT enf)
{
	ULONG size;
	BOOL res;
	DWORD err;

	memset(outBuffer, 0, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));

	size = MWINSECURITY_OUTBUFF_SIZE;
	res  = GetUserNameEx(enf, outBuffer, &size);
	if(!res){
		memset(outBuffer, 0, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));
		err = GetLastError();
		return NULL;
	}

	outBuffer[MWINSECURITY_OUTBUFF_SIZE - 1] = 0;
	return outBuffer;
}

LPTSTR MWinSecurity::RetrieveUserName(void)
{
	DWORD size;
	BOOL  res;
	DWORD err;

	memset(outBuffer, 0, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));
	size = MWINSECURITY_OUTBUFF_SIZE;

	res  = GetUserName(outBuffer, &size);
	if(!res){
		memset(outBuffer, 0, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));
		err = GetLastError();
		return NULL;
	}

	outBuffer[MWINSECURITY_OUTBUFF_SIZE - 1] = 0;
	return outBuffer;
}


LPTSTR MWinSecurity::RetrieveUserName_FQDN(void)
{
	return RetrieveFormatedUserName(NameFullyQualifiedDN);
}

LPTSTR MWinSecurity::RetrieveUserName_FriendlyDisplay(void)
{
	return RetrieveFormatedUserName(NameDisplay);
}

LPTSTR MWinSecurity::RetrieveUserName_UniqueId(void)
{
	return RetrieveFormatedUserName(NameUniqueId);
}

LPTSTR MWinSecurity::RetrieveUserName_Canonical(void)
{
	return RetrieveFormatedUserName(NameCanonical);
}

LPTSTR MWinSecurity::RetrieveUserName_Principal(void)
{
	return RetrieveFormatedUserName(NameUserPrincipal);
}

LPTSTR MWinSecurity::RetrieveUserName_DNSDomain(void)
{
	return RetrieveFormatedUserName(NameDnsDomain);
}

PSID MWinSecurity::CreateUserSID(void)
{
	BOOL         res;
	BYTE*        sidBuff;
	DWORD        sidSize;
	DWORD        cchReferencedDomainName;
	SID_NAME_USE sidNameUse;
	DWORD        err;
	LPTSTR       accountName;
	PSID         sid;

	accountName = RetrieveUserName();
	if(accountName==NULL)
		return NULL;

	memset(domainNameBuffer, 0, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));

	sidSize = 0;
	cchReferencedDomainName = MWINSECURITY_OUTBUFF_SIZE;
	res = LookupAccountName(
				NULL,
				accountName,
				NULL,
				&sidSize,
				domainNameBuffer,
				&cchReferencedDomainName,
				&sidNameUse);
	if(res==0){
		err = GetLastError();
		if(err!=ERROR_INSUFFICIENT_BUFFER)		
			return NULL;

		try{
			sidBuff = new BYTE[sidSize];
		}
		catch(...){
			sidBuff = NULL;
		}
		if(sidBuff==NULL)
			return NULL;

		sid = (PSID)sidBuff;
		cchReferencedDomainName = MWINSECURITY_OUTBUFF_SIZE;
		res = LookupAccountName(
				NULL,
				accountName,
				sid,
				&sidSize,
				domainNameBuffer,
				&cchReferencedDomainName,
				&sidNameUse);
		if(res==0){
			memset(domainNameBuffer, 0, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));
			return NULL;
		}
	}

	if(!IsValidSid(sid))
		return NULL;

	return sid;
}

LPTSTR MWinSecurity::GetAccountName(PSID sidIn, LPCTSTR machineNameIn)
{
	BOOL res;
	SID_NAME_USE snu;
	DWORD sizeName, sizeDomain;

	if(sidIn==NULL) return NULL;

	SecureZeroMemory(outBuffer, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));
	SecureZeroMemory(domainNameBuffer, MWINSECURITY_OUTBUFF_SIZE * sizeof(TCHAR));

	sizeName = MWINSECURITY_OUTBUFF_SIZE;
	sizeDomain = MWINSECURITY_OUTBUFF_SIZE;
	res = LookupAccountSid(machineNameIn, sidIn, outBuffer, &sizeName, domainNameBuffer, &sizeDomain, &snu);
	if(!res){
		DWORD err;
		err = GetLastError();
		err = err;
	}

	if(res) return outBuffer;

	return NULL;
}

LPTSTR MWinSecurity::GetUserDomainName(void)
{
	return domainNameBuffer;
}

void MWinSecurity::DestroyUserSID(PSID sidIn)
{
	BYTE* sidBuff;

	if(sidIn!=NULL){
		sidBuff = (BYTE*)sidIn;
		delete[] sidBuff;
	}
}

bool MWinSecurity::IsValidSID(PSID sidIn)
{
	BOOL res;

	if(sidIn==NULL) return false;

	try{
		res = IsValidSid(sidIn);
	}
	catch(...){
		res = FALSE;
	}
	return res ? true : false;
}
